/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-02-21     tinnu       the first version
 */
#include "tarm_uart.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

uint8_t g_uartDateBuf[100];
uint8_t g_uartDateBuf2[100];

void PRINTF_UART0OnSize(const char *data, uint16_t length)
{
//    for(int i=0; i<length; i++)
//    {
//        USART_SendData(USART1, data[i]);
//        while(USART_GetFlagStatus(USART1, USART_FLAG_TDE) == RESET);
//    }
}

void PRINTF_UART0(const char *data)
{
//    int len = strlen(data);
//    for(int i=0; i<len; i++)
//    {
//        USART_SendData(USART1, data[i]);
//        while(USART_GetFlagStatus(USART1, USART_FLAG_TDE) == RESET);
//    }
}

void PRINTF_UART1OnSize(const char *data, uint16_t length)
{
    for(int i=0; i<length; i++)
    {
        USART_SendData(USART2, data[i]);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TDE) == RESET);
    }
}

void PRINTF_UART1(const char *data)
{
    int len = strlen(data);
    for(int i=0; i<len; i++)
    {
        USART_SendData(USART2, data[i]);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TDE) == RESET);
    }
}

void Uart2DMA_Configuration(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOA, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_DMA1, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_USART2, ENABLE);
    //IO
    /* Configure USART2 Rx as input floating */
    GPIO_InitType GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* Configure USART2 Tx as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pins = GPIO_Pins_2;
    GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //USART2
    USART_InitType USART_InitStructure;
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    /* Configure USART2 */
    USART_Init(USART2, &USART_InitStructure);

    DMA_Reset(DMA1_Channel6);
    DMA_InitType DMA_InitStructure;
    DMA_DefaultInitParaConfig(&DMA_InitStructure);
    DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)g_uartDateBuf2;
    DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALSRC;
    DMA_InitStructure.DMA_BufferSize = 100;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
    DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_BYTE;
    DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
    DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
    DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
    DMA_Init(DMA1_Channel6, &DMA_InitStructure);

    NVIC_InitType NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    USART_INTConfig(USART2, USART_INT_IDLEF, ENABLE);
    USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
    USART_Cmd(USART2, ENABLE);
    DMA_ChannelEnable(DMA1_Channel6, ENABLE);
}


void Uart1DMA_Configuration(void)
{
    USART_Cmd(USART1, DISABLE);

    RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_DMA1, ENABLE);
    DMA_InitType DMA_InitStructure;

    // USART2 TX DMA1 Channel (triggered by USART2 Tx event) Config
    DMA_Reset(DMA1_Channel5);
    DMA_DefaultInitParaConfig(&DMA_InitStructure);
    DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)g_uartDateBuf;
    DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALSRC;
    DMA_InitStructure.DMA_BufferSize = 100;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
    DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_BYTE;
    DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_MODE_CIRCULAR;
    DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
    DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);

    USART_InitType USART_InitStructure;
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    NVIC_InitType NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    USART_INTConfig(USART1, USART_INT_IDLEF, ENABLE);
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    USART_Cmd(USART1, ENABLE);
    DMA_ChannelEnable(DMA1_Channel5, ENABLE);
}

struct _StructUartBuf StructUart0RxBuf = {0, 0, ""};
struct _StructUartBuf StructUart1RxBuf = {0, 0, ""};
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_INT_IDLEF) != RESET)
    {
        DMA_ChannelEnable(DMA1_Channel5, DISABLE);
        unsigned char get_len = 100 - DMA_GetCurrDataCounter(DMA1_Channel5);

        get_len = get_len>_UARTSAVEBUFSIZE?_UARTSAVEBUFSIZE:get_len;
        memset(StructUart0RxBuf.Rxbuf, 0, _UARTSAVEBUFSIZE);
        StructUart0RxBuf.RxbufSize = get_len;
        strncpy(StructUart0RxBuf.Rxbuf, (char*)g_uartDateBuf, get_len);
        StructUart0RxBuf.FinishFlag = 2;

        DMA1_Channel5->TCNT = 100;
        DMA_ChannelEnable(DMA1_Channel5, ENABLE);
        USART_ReceiveData(USART1);
    }
}

void USART2_IRQHandler(void)
{
    if(USART_GetITStatus(USART2, USART_INT_IDLEF) != RESET)
    {
        DMA_ChannelEnable(DMA1_Channel6, DISABLE);
        unsigned char get_len = 100 - DMA_GetCurrDataCounter(DMA1_Channel6);

        get_len = get_len>_UARTSAVEBUFSIZE?_UARTSAVEBUFSIZE:get_len;
        memset(StructUart1RxBuf.Rxbuf, 0, _UARTSAVEBUFSIZE);
        StructUart1RxBuf.RxbufSize = get_len;
        strncpy(StructUart1RxBuf.Rxbuf, (char*)g_uartDateBuf2, get_len);
        StructUart1RxBuf.FinishFlag = 2;

        DMA1_Channel6->TCNT = 100;
        DMA_ChannelEnable(DMA1_Channel6, ENABLE);
        USART_ReceiveData(USART2);
    }
}
